package generator.mybatis.plugin;

import com.itfsw.mybatis.generator.plugins.utils.JavaElementGeneratorTools;
import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.FullyQualifiedTable;
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.Plugin;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.Interface;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.internal.util.JavaBeansUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;

import static org.mybatis.generator.internal.util.StringUtility.stringHasValue;

/**
 * 2019/4/23
 * 生成dao层实现
 *
 * @author machuanpeng
 */
public class MyDaoImplPlugin extends PluginAdapter {
    /**
     * 返回参数dto包路径
     */
    private String responsePackage;
    /**
     * 包路径
     */
    private String targetPackage;
    /**
     * 目标
     */
    private String targetProject;
    /**
     * 文件名后缀（可自定义Dao、Service。默认Dao）
     */
    private String suffix;

    private IntrospectedTable introspectedTable;

    private String fieldName;

    @Override
    public boolean validate(List<String> warnings) {
        responsePackage = properties.getProperty("responsePackage");
        targetPackage = properties.getProperty("targetPackage");
        targetProject = properties.getProperty("targetProject");
        if (!stringHasValue(targetProject)) {
            targetProject = "mybatis/src/main/java";
        }
        suffix = properties.getProperty("suffix");
        if (!stringHasValue(suffix)) {
            suffix = "Dao";
        }
        return stringHasValue(targetPackage) && stringHasValue(responsePackage);
    }

    /**
     * 添加文件.
     * 2019/6/14
     *
     * @param introspectedTable introspectedTable
     * @return java.util.List<org.mybatis.generator.api.GeneratedJavaFile>
     * @author machuanpeng
     */
    @Override
    public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
        importedTypes.add(new FullyQualifiedJavaType("org.springframework.util.ObjectUtils"));

        List<GeneratedJavaFile> generatedJavaFiles = new ArrayList<>();
        this.introspectedTable = introspectedTable;
        FullyQualifiedTable fullyQualifiedTable = introspectedTable.getFullyQualifiedTable();

        //model名称
        String domainName = fullyQualifiedTable.getDomainObjectName();
        //返回类型
        FullyQualifiedJavaType listType = FullyQualifiedJavaType.getNewListInstance();
        FullyQualifiedJavaType javaType = new FullyQualifiedJavaType(responsePackage + "." + domainName + "ResDTO");
        listType.addTypeArgument(javaType);

        importedTypes.add(javaType);
        importedTypes.add(FullyQualifiedJavaType.getNewListInstance());

        //dao层接口
        FullyQualifiedJavaType interfaceType = new FullyQualifiedJavaType(targetPackage + "." + domainName + suffix);
        Interface interfaze = new Interface(interfaceType);
        interfaze.setVisibility(JavaVisibility.PUBLIC);

        //dao层实现
        importedTypes.add(interfaceType);
        FullyQualifiedJavaType topLevelClassType = new FullyQualifiedJavaType(targetPackage + ".impl." + domainName + suffix + "Impl");
        TopLevelClass topLevelClass = new TopLevelClass(topLevelClassType);
        topLevelClass.setVisibility(JavaVisibility.PUBLIC);
        topLevelClass.addSuperInterface(interfaceType);
        topLevelClass.addAnnotation("@Repository");
        importedTypes.add(new FullyQualifiedJavaType("org.springframework.stereotype.Repository"));
        Field field = new Field();
        field.addAnnotation("@Autowired");
        field.setVisibility(JavaVisibility.PRIVATE);
        String javaMapperTypeStr = introspectedTable.getMyBatis3JavaMapperType();
        FullyQualifiedJavaType javaMapperType = new FullyQualifiedJavaType(javaMapperTypeStr);
        field.setType(javaMapperType);
        fieldName = toLowerCaseFirstOne(javaMapperType.getShortName());
        field.setName(fieldName);
        importedTypes.add(new FullyQualifiedJavaType("org.springframework.beans.factory.annotation.Autowired"));
        importedTypes.add(javaMapperType);
        topLevelClass.addField(field);

        CommentGenerator commentGenerator = context.getCommentGenerator();
        commentGenerator.addModelClassComment(topLevelClass, introspectedTable);

        addCountByExampleMethod(topLevelClass);
        addDeleteByExampleMethod(topLevelClass);
        addDeleteByPrimaryKeyMethod(topLevelClass);
        addInsertMethod(topLevelClass);
        addInsertSelectiveMethod(topLevelClass);
        addSelectByExampleWithBLOBsMethod(topLevelClass, listType);
        addSelectByExampleWithoutBLOBsMethod(topLevelClass, listType);
        addSelectByPrimaryKeyMethod(topLevelClass, javaType);
        addSelectOneByExampleMethod(topLevelClass, javaType);
        addUpdateByExampleSelectiveMethod(topLevelClass);
        addUpdateByExampleWithBLOBsMethod(topLevelClass);
        addUpdateByExampleWithoutBLOBsMethod(topLevelClass);
        addUpdateByPrimaryKeySelectiveMethod(topLevelClass);
        addUpdateByPrimaryKeyWithBLOBsMethod(topLevelClass);
        addUpdateByPrimaryKeyWithoutBLOBsMethod(topLevelClass);
        addBatchInsertMethod(topLevelClass);

        Plugin plugin = context.getPlugins();
        if (plugin.clientGenerated(interfaze, topLevelClass, introspectedTable)) {
            List<Method> methods = topLevelClass.getMethods();
            methods.removeIf(method -> Objects.equals(method.getName(), "batchInsert") && Objects.equals(method.getReturnType().getShortName(),
                    "int"));
            topLevelClass.addImportedTypes(importedTypes);
            GeneratedJavaFile generatedJavaFile = new GeneratedJavaFile(topLevelClass, targetProject, context.getJavaFormatter());
            generatedJavaFiles.add(generatedJavaFile);
        }
        return generatedJavaFiles;
    }

    /**
     * 首字母转为小写.
     * 2019/6/17
     *
     * @param s s
     * @return java.lang.String
     * @author machuanpeng
     */
    private String toLowerCaseFirstOne(String s) {
        if (Character.isLowerCase(s.charAt(0))) {
            return s;
        } else {
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
        }
    }

    /**
     * 添加批量插入方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addBatchInsertMethod(TopLevelClass topLevelClass) {
        FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
        Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
        importedTypes.add(fullyQualifiedJavaType);

        FullyQualifiedJavaType listType = FullyQualifiedJavaType.getNewListInstance();
        FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
        listType.addTypeArgument(parameterType);
        importedTypes.add(listType);
        importedTypes.add(parameterType);
        Method method = JavaElementGeneratorTools.generateMethod("batchInsert", JavaVisibility.PUBLIC, fullyQualifiedJavaType,
                new Parameter(listType, "list"));
        method.addAnnotation("@Override");
        method.addBodyLine("if (ObjectUtils.isEmpty(list)) {");
        method.addBodyLine("return false;");
        method.addBodyLine("}");
        importedTypes.add(FullyQualifiedJavaType.getIntInstance());
        StringBuilder stringBuilder = new StringBuilder("int result = ");
        stringBuilder.append(fieldName);
        stringBuilder.append(".");
        stringBuilder.append("batchInsert");
        stringBuilder.append("(list);");
        method.addBodyLine(stringBuilder.toString());
        method.addBodyLine("return result > 0;");
        context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

        if (context.getPlugins()
                .clientUpdateByExampleSelectiveMethodGenerated(method, topLevelClass,
                        introspectedTable)) {
            topLevelClass.addImportedTypes(importedTypes);
            topLevelClass.addMethod(method);
        }
    }

    /**
     * 添加根据条件查询单条方法.
     * 2019/6/15
     *
     * @param topLevelClass          topLevelClass
     * @param fullyQualifiedJavaType fullyQualifiedJavaType
     * @return void
     * @author machuanpeng
     */
    private void addSelectOneByExampleMethod(TopLevelClass topLevelClass, FullyQualifiedJavaType fullyQualifiedJavaType) {
        if (introspectedTable.getRules().generateSelectByExampleWithoutBLOBs()) {
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getExampleType());
            importedTypes.add(type);
            importedTypes.add(fullyQualifiedJavaType);

            Method method = JavaElementGeneratorTools.generateMethod("selectOneByExample", JavaVisibility.PUBLIC,
                    fullyQualifiedJavaType, new Parameter(type, "example"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(example)) {");
            method.addBodyLine("return null;");
            method.addBodyLine("}");
            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(parameterType.getShortName());
            stringBuilder.append(" result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append("selectOneByExample");
            stringBuilder.append("(example);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("if (ObjectUtils.isEmpty(result)) {");
            method.addBodyLine("return null;");
            method.addBodyLine("}");
            method.addBodyLine("//todo 转换返回dto对象");
            method.addBodyLine("return null;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientDeleteByExampleMethodGenerated(
                    method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过条件查询记录总数.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addCountByExampleMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateCountByExample()) {
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            FullyQualifiedJavaType fullyQualifiedJavaType = new FullyQualifiedJavaType("long");
            FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getExampleType());
            importedTypes.add(type);
            importedTypes.add(fullyQualifiedJavaType);
            String methodName = introspectedTable.getCountByExampleStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName, JavaVisibility.PUBLIC,
                    fullyQualifiedJavaType, new Parameter(type, "example"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(example)) {");
            method.addBodyLine("return 0;");
            method.addBodyLine("}");
            StringBuilder stringBuilder = new StringBuilder("return ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(example);");
            method.addBodyLine(stringBuilder.toString());
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientDeleteByExampleMethodGenerated(
                    method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过条件删除方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addDeleteByExampleMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateDeleteByExample()) {
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getExampleType());
            importedTypes.add(type);
            importedTypes.add(fullyQualifiedJavaType);
            String methodName = introspectedTable.getDeleteByExampleStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName, JavaVisibility.PUBLIC,
                    fullyQualifiedJavaType, new Parameter(type, "example"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(example)) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(example);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientDeleteByExampleMethodGenerated(
                    method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过主键删除方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addDeleteByPrimaryKeyMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateDeleteByPrimaryKey()) {
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(fullyQualifiedJavaType);

            Parameter parameter = null;

            if (introspectedTable.getRules().generatePrimaryKeyClass()) {
                FullyQualifiedJavaType type = new FullyQualifiedJavaType(
                        introspectedTable.getPrimaryKeyType());
                importedTypes.add(type);
                parameter = new Parameter(type, "key");
            } else {
                List<IntrospectedColumn> introspectedColumns = introspectedTable
                        .getPrimaryKeyColumns();
                for (IntrospectedColumn introspectedColumn : introspectedColumns) {
                    FullyQualifiedJavaType type = introspectedColumn
                            .getFullyQualifiedJavaType();
                    importedTypes.add(type);
                    parameter = new Parameter(type, introspectedColumn
                            .getJavaProperty());
                }
            }
            String methodName = introspectedTable.getDeleteByPrimaryKeyStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName, JavaVisibility.PUBLIC,
                    fullyQualifiedJavaType, parameter);
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(" + parameter.getName() + ")) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(" + parameter.getName() + ");");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientDeleteByPrimaryKeyMethodGenerated(
                    method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加插入方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addInsertMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateInsert()) {
            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(fullyQualifiedJavaType);
            importedTypes.add(parameterType);
            String methodName = introspectedTable.getInsertStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName,
                    JavaVisibility.PUBLIC, fullyQualifiedJavaType, new Parameter(parameterType, "record"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(record)) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(record);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientInsertMethodGenerated(method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加插入非空字段方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addInsertSelectiveMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateInsertSelective()) {
            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(fullyQualifiedJavaType);
            importedTypes.add(parameterType);
            String methodName = introspectedTable.getInsertSelectiveStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName,
                    JavaVisibility.PUBLIC, fullyQualifiedJavaType, new Parameter(parameterType, "record"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(record)) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(record);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientInsertMethodGenerated(method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过条件查询列表方法.
     * 2019/6/17
     *
     * @param topLevelClass  topLevelClass
     * @param returnJavaType returnJavaType
     * @return void
     * @author machuanpeng
     */
    private void addSelectByExampleWithBLOBsMethod(TopLevelClass topLevelClass, FullyQualifiedJavaType returnJavaType) {
        if (introspectedTable.getRules().generateSelectByExampleWithBLOBs()) {
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getExampleType());
            importedTypes.add(type);
            importedTypes.add(returnJavaType);
            importedTypes.add(new FullyQualifiedJavaType("java.util.ArrayList"));

            String methodName = introspectedTable.getSelectByExampleWithBLOBsStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName,
                    JavaVisibility.PUBLIC,
                    returnJavaType, new Parameter(type, "example"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(example)) {");
            method.addBodyLine("return new ArrayList<>();");
            method.addBodyLine("}");
            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            StringBuilder stringBuilder = new StringBuilder("List<");
            stringBuilder.append(parameterType.getShortName());
            stringBuilder.append("> result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(example);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("if (ObjectUtils.isEmpty(result)) {");
            method.addBodyLine("return new ArrayList<>();");
            method.addBodyLine("}");
            method.addBodyLine("//todo 转换返回dto对象");
            method.addBodyLine("return new ArrayList<>();");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientDeleteByExampleMethodGenerated(
                    method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过条件查询列表方法.
     * 2019/6/17
     *
     * @param topLevelClass  topLevelClass
     * @param returnJavaType returnJavaType
     * @return void
     * @author machuanpeng
     */
    private void addSelectByExampleWithoutBLOBsMethod(TopLevelClass topLevelClass, FullyQualifiedJavaType returnJavaType) {
        if (introspectedTable.getRules().generateSelectByExampleWithoutBLOBs()) {
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            FullyQualifiedJavaType type = new FullyQualifiedJavaType(introspectedTable.getExampleType());
            importedTypes.add(type);
            importedTypes.add(returnJavaType);
            importedTypes.add(new FullyQualifiedJavaType("java.util.ArrayList"));

            String methodName = introspectedTable.getSelectByExampleStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName,
                    JavaVisibility.PUBLIC,
                    returnJavaType, new Parameter(type, "example"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(example)) {");
            method.addBodyLine("return new ArrayList<>();");
            method.addBodyLine("}");
            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            StringBuilder stringBuilder = new StringBuilder("List<");
            stringBuilder.append(parameterType.getShortName());
            stringBuilder.append("> result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(example);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("if (ObjectUtils.isEmpty(result)) {");
            method.addBodyLine("return new ArrayList<>();");
            method.addBodyLine("}");
            method.addBodyLine("//todo 转换返回dto对象");
            method.addBodyLine("return new ArrayList<>();");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientDeleteByExampleMethodGenerated(
                    method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过主键查询方法.
     * 2019/6/17
     *
     * @param topLevelClass  topLevelClass
     * @param returnJavaType returnJavaType
     * @return void
     * @author machuanpeng
     */
    private void addSelectByPrimaryKeyMethod(TopLevelClass topLevelClass, FullyQualifiedJavaType returnJavaType) {
        if (introspectedTable.getRules().generateSelectByPrimaryKey()) {
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(returnJavaType);

            Parameter parameter = null;

            if (introspectedTable.getRules().generatePrimaryKeyClass()) {
                FullyQualifiedJavaType type = new FullyQualifiedJavaType(
                        introspectedTable.getPrimaryKeyType());
                importedTypes.add(type);
                parameter = new Parameter(type, "key");
            } else {
                List<IntrospectedColumn> introspectedColumns = introspectedTable
                        .getPrimaryKeyColumns();
                for (IntrospectedColumn introspectedColumn : introspectedColumns) {
                    FullyQualifiedJavaType type = introspectedColumn
                            .getFullyQualifiedJavaType();
                    importedTypes.add(type);
                    parameter = new Parameter(type, introspectedColumn
                            .getJavaProperty());
                }
            }

            String methodName = introspectedTable.getSelectByPrimaryKeyStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName, JavaVisibility.PUBLIC,
                    returnJavaType, parameter);
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(" + parameter.getName() + ")) {");
            method.addBodyLine("return null;");
            method.addBodyLine("}");
            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(parameterType.getShortName());
            stringBuilder.append(" result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(" + parameter.getName() + ");");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("if (ObjectUtils.isEmpty(result)) {");
            method.addBodyLine("return null;");
            method.addBodyLine("}");
            method.addBodyLine("//todo 转换返回dto对象");
            method.addBodyLine("return null;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientDeleteByPrimaryKeyMethodGenerated(
                    method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过条件更新非空字段方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addUpdateByExampleSelectiveMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateUpdateByExampleSelective()) {
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(fullyQualifiedJavaType);

            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            importedTypes.add(parameterType);

            FullyQualifiedJavaType exampleType = new FullyQualifiedJavaType(introspectedTable.getExampleType());
            importedTypes.add(exampleType);
            String methodName = introspectedTable.getUpdateByExampleSelectiveStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName,
                    JavaVisibility.PUBLIC,
                    fullyQualifiedJavaType, new Parameter(parameterType, "record"), new Parameter(exampleType, "example"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(record) || ObjectUtils.isEmpty(example)) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(record, example);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientUpdateByExampleSelectiveMethodGenerated(method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过条件更新方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addUpdateByExampleWithBLOBsMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateUpdateByExampleWithBLOBs()) {
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(fullyQualifiedJavaType);

            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            importedTypes.add(parameterType);

            FullyQualifiedJavaType exampleType = new FullyQualifiedJavaType(introspectedTable.getExampleType());
            importedTypes.add(exampleType);
            String methodName = introspectedTable.getUpdateByExampleWithBLOBsStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName,
                    JavaVisibility.PUBLIC,
                    fullyQualifiedJavaType, new Parameter(parameterType, "record"), new Parameter(exampleType, "example"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(record) || ObjectUtils.isEmpty(example)) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(record, example);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientUpdateByExampleSelectiveMethodGenerated(method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过条件更新方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addUpdateByExampleWithoutBLOBsMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateUpdateByExampleWithoutBLOBs()) {
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(fullyQualifiedJavaType);

            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            importedTypes.add(parameterType);

            FullyQualifiedJavaType exampleType = new FullyQualifiedJavaType(introspectedTable.getExampleType());
            importedTypes.add(exampleType);

            String methodName = introspectedTable.getUpdateByExampleStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName, JavaVisibility.PUBLIC,
                    fullyQualifiedJavaType, new Parameter(parameterType, "record"), new Parameter(exampleType, "example"));
            method.addAnnotation("@Override");
            method.addBodyLine("if (ObjectUtils.isEmpty(record) || ObjectUtils.isEmpty(example)) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(record, example);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientUpdateByExampleSelectiveMethodGenerated(method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过主键更新非空字段方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addUpdateByPrimaryKeySelectiveMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateUpdateByPrimaryKeySelective()) {
            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(fullyQualifiedJavaType);
            importedTypes.add(parameterType);
            String methodName = introspectedTable.getUpdateByPrimaryKeySelectiveStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName,
                    JavaVisibility.PUBLIC, fullyQualifiedJavaType, new Parameter(parameterType, "record"));
            method.addAnnotation("@Override");
            List<IntrospectedColumn> introspectedColumns = introspectedTable.getPrimaryKeyColumns();
            String getMethodName = null;
            for (IntrospectedColumn introspectedColumn : introspectedColumns) {
                FullyQualifiedJavaType type = introspectedColumn.getFullyQualifiedJavaType();
                String property = introspectedColumn.getJavaProperty();
                getMethodName = JavaBeansUtil.getGetterMethodName(property, type);
            }
            method.addBodyLine("if (ObjectUtils.isEmpty(record) || ObjectUtils.isEmpty(record." + getMethodName + "())) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(record);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientInsertMethodGenerated(method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过主键更新方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addUpdateByPrimaryKeyWithBLOBsMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateUpdateByPrimaryKeyWithBLOBs()) {
            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(fullyQualifiedJavaType);
            importedTypes.add(parameterType);

            String methodName = introspectedTable.getUpdateByPrimaryKeyWithBLOBsStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName,
                    JavaVisibility.PUBLIC, fullyQualifiedJavaType, new Parameter(parameterType, "record"));
            method.addAnnotation("@Override");
            List<IntrospectedColumn> introspectedColumns = introspectedTable.getPrimaryKeyColumns();
            String getMethodName = null;
            for (IntrospectedColumn introspectedColumn : introspectedColumns) {
                FullyQualifiedJavaType type = introspectedColumn.getFullyQualifiedJavaType();
                String property = introspectedColumn.getJavaProperty();
                getMethodName = JavaBeansUtil.getGetterMethodName(property, type);
            }
            method.addBodyLine("if (ObjectUtils.isEmpty(record) || ObjectUtils.isEmpty(record." + getMethodName + "())) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(record);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientInsertMethodGenerated(method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

    /**
     * 添加通过主键更新方法.
     * 2019/6/17
     *
     * @param topLevelClass topLevelClass
     * @return void
     * @author machuanpeng
     */
    private void addUpdateByPrimaryKeyWithoutBLOBsMethod(TopLevelClass topLevelClass) {
        if (introspectedTable.getRules().generateUpdateByPrimaryKeyWithoutBLOBs()) {
            FullyQualifiedJavaType parameterType = introspectedTable.getRules().calculateAllFieldsClass();
            FullyQualifiedJavaType fullyQualifiedJavaType = FullyQualifiedJavaType.getBooleanPrimitiveInstance();
            Set<FullyQualifiedJavaType> importedTypes = new TreeSet<>();
            importedTypes.add(fullyQualifiedJavaType);
            importedTypes.add(parameterType);

            String methodName = introspectedTable.getUpdateByPrimaryKeyStatementId();
            Method method = JavaElementGeneratorTools.generateMethod(methodName, JavaVisibility.PUBLIC,
                    fullyQualifiedJavaType, new Parameter(parameterType, "record"));
            method.addAnnotation("@Override");
            List<IntrospectedColumn> introspectedColumns = introspectedTable.getPrimaryKeyColumns();
            String getMethodName = null;
            for (IntrospectedColumn introspectedColumn : introspectedColumns) {
                FullyQualifiedJavaType type = introspectedColumn.getFullyQualifiedJavaType();
                String property = introspectedColumn.getJavaProperty();
                getMethodName = JavaBeansUtil.getGetterMethodName(property, type);
            }
            method.addBodyLine("if (ObjectUtils.isEmpty(record) || ObjectUtils.isEmpty(record." + getMethodName + "())) {");
            method.addBodyLine("return false;");
            method.addBodyLine("}");
            importedTypes.add(FullyQualifiedJavaType.getIntInstance());
            StringBuilder stringBuilder = new StringBuilder("int result = ");
            stringBuilder.append(fieldName);
            stringBuilder.append(".");
            stringBuilder.append(methodName);
            stringBuilder.append("(record);");
            method.addBodyLine(stringBuilder.toString());
            method.addBodyLine("return result > 0;");
            context.getCommentGenerator().addGeneralMethodComment(method, introspectedTable);

            if (context.getPlugins().clientInsertMethodGenerated(method, topLevelClass, introspectedTable)) {
                topLevelClass.addImportedTypes(importedTypes);
                topLevelClass.addMethod(method);
            }
        }
    }

}
